//
//  IAPAngel.m
//  BBQ
//
//  Created by danal Luo on 10/26/12.
//
//

#import "IAPAngel.h"
#import "GTMBase64.h"

@interface IAPAngel ()
@property (retain, nonatomic) SKProductsRequest *request;
@property (retain, nonatomic) SKProduct *product;
@end


@implementation IAPAngel
@synthesize request = _request;
@synthesize product = _product;
@synthesize delegate  = _delegate;
@synthesize purchasing = _purchasing;
@synthesize verifyReceiptUrl = _verifyReceiptUrl;

- (void)dealloc{
    self.delegate = nil;
    [_verifyReceiptUrl release];    _verifyReceiptUrl = nil;
    [_request release]; _request = nil;
    [_product release]; _product = nil;
    [super dealloc];
}


static IAPAngel *_sharedIAPAngel = nil;
+ (id)shared{
    @synchronized(self){
        if (_sharedIAPAngel == nil) {
            _sharedIAPAngel = [[self alloc] init];
        }
        return _sharedIAPAngel;
    }
}

- (id)init{
    self = [super init];
    if (self) {
         [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        self.verifyReceiptUrl = @"http://mobiwc.duapp.com/iap/validate.php";
    }
    return self;
}

- (BOOL)isPurchasedProduct:(NSString *)productId{
    NSString *key = [self keyForProductIdentifier:productId];
    id val = [[NSUserDefaults standardUserDefaults] objectForKey:key];
    return val != nil;
}

- (void)requestProduct:(NSString *)productIdentifier{
    _purchasing = YES;
    NSSet *set = [NSSet setWithObject:productIdentifier];
    self.request = [[[SKProductsRequest alloc] initWithProductIdentifiers:set] autorelease];
    self.request.delegate = self;
    [self.request start];
}

- (void)cancelRequest{
    _purchasing = NO;
    [self.request cancel];
}

- (void)makePayment:(SKProduct *)product{
    if ([SKPaymentQueue canMakePayments]) {
        SKPayment *payment = [SKPayment paymentWithProduct:product];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
                                                        message:@"ERROR:SKPaymentQueue cannot make payments"
                                                       delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil];
        [alert show];
        [alert release];
    }
}

//Restoer transactions on new device
- (void)restore{
    _purchasing = YES;
    if ([SKPaymentQueue canMakePayments]) {
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
                                                        message:@"ERROR:SKPaymentQueue cannot make payments"
                                                       delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil];
        [alert show];
        [alert release];
        _purchasing = NO;
    }
}

//Use this to judge the non-consumable product is purchased or restored
- (NSString *)receiptForProduct:(NSString *)productIdentifier{
    NSString *key = [self keyForProductIdentifier:productIdentifier];
    return [[NSUserDefaults standardUserDefaults] objectForKey:key];
}

//Generate a key use product identifier for saving receipts
- (NSString *)keyForProductIdentifier:(NSString *)identifier{
    return [identifier stringByReplacingOccurrencesOfString:@"." withString:@"-"];
}

//
// enable pro features
//

- (void)recordTransaction:(SKPaymentTransaction *)transaction
{
    // save the transaction receipt to disk
    NSString *key = [self keyForProductIdentifier:transaction.payment.productIdentifier];
    [[NSUserDefaults standardUserDefaults] setValue:transaction.transactionReceipt forKey:key];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (void)provideContent:(NSString *)productIdentifier
{
    NSString *key = [self keyForProductIdentifier:productIdentifier];
    // enable the pro features
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:key];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

//
// removes the transaction from the queue and posts a notification with the transaction result
//
- (void)finishTransaction:(SKPaymentTransaction *)transaction wasSuccessful:(BOOL)wasSuccessful
{
    // remove the transaction from the payment queue.
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
    
    NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:transaction,@"Transaction",
                       [NSNumber numberWithBool:wasSuccessful],@"Success",
                       nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationPurchaseComplete object:nil userInfo:d];
//    NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:transaction, @"transaction" , nil];
    
    _purchasing = NO;
    
    if(_delegate && [_delegate respondsToSelector:@selector(angelDidCompleteTransaction:successful:)]){
        [_delegate angelDidCompleteTransaction:transaction successful:wasSuccessful];
    }

}

//
// called when the transaction was successful
//
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
    [self recordTransaction:transaction];
    [self provideContent:transaction.payment.productIdentifier];
    [self finishTransaction:transaction wasSuccessful:YES];
}

//
// called when a transaction has been restored and and successfully completed
//
- (void)restoreTransaction:(SKPaymentTransaction *)transaction
{
#ifdef IAP_DEBUG
    NSLog(@"%s",__func__);
#endif
    [self recordTransaction:transaction.originalTransaction];
    [self provideContent:transaction.originalTransaction.payment.productIdentifier];
    [self finishTransaction:transaction wasSuccessful:YES];
}

//
// called when a transaction has failed
//
- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
#ifdef IAP_DEBUG
    NSLog(@"%s",__func__);
#endif
    if (transaction.error.code != SKErrorPaymentCancelled)
    {
        // error!
        [self finishTransaction:transaction wasSuccessful:NO];
    }
    else
    {
        // this is fine, the user just cancelled, so don’t notify
//        [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
        [self finishTransaction:transaction wasSuccessful:NO];
    }
}

- (void)transactionPurchasing:(SKPaymentTransaction *)t{
#ifdef IAP_DEBUG
    NSLog(@"%s",__func__);
#endif
}

#pragma mark - Server Validate
- (BOOL)verifyReceipt:(NSData*)receipt
{
    MSHTTPRequest *request = [MSHTTPRequest requestWithUrl:self.verifyReceiptUrl];
    request.postMethod = YES;
    request.parseJson = YES;
    [request addValue:[GTMBase64 stringByEncodingData:receipt] forField:@"receipt"];
#ifdef DEBUG
    [request addValue:@"1" forField:@"sandbox"];
#else
    [request addValue:@"0" forField:@"sandbox"];    
#endif
    id result =[request startSync:15];
    if (result && [result isKindOfClass:[NSDictionary class]]) {
        ECHO(@"%@", result);
        BOOL success = [[result objectForKey:@"success"] boolValue];
        return success;
    }
    
    return NO;
}

#pragma mark - ProductsRequest Delegates

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
#ifdef IAP_DEBUG
    NSLog(@"Received Products:%@",response.products);
    NSLog(@"Invalid Products:%@",response.invalidProductIdentifiers);
#endif

    if (_delegate && [_delegate respondsToSelector:@selector(angelDidReceiveProducts:)]) {
        [_delegate angelDidReceiveProducts:response.products];
    }
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
#ifdef IAP_DEBUG
    NSLog(@"%@",error);
#endif
    _purchasing = NO;
    if (_delegate && [_delegate respondsToSelector:@selector(angelRequestDidFailWithError:)]) {
        [_delegate angelRequestDidFailWithError:error];
    }
}


#pragma mark - PaymentTransaction Delegates

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
#ifdef IAP_DEBUG
    NSLog(@"updated Transactions:%@",transactions);
#endif
    for (SKPaymentTransaction *t in transactions)
    {
        switch (t.transactionState)
        {
            case SKPaymentTransactionStatePurchased:
                [self completeTransaction:t];
                break;
            case SKPaymentTransactionStateFailed:
                [self failedTransaction:t];
                break;
            case SKPaymentTransactionStateRestored:
                [self restoreTransaction:t];
                break;
            case SKPaymentTransactionStatePurchasing:
                [self transactionPurchasing:t];
                break;
            default:
                break;
        }
    }
}

- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue{
#ifdef IAP_DEBUG
    NSLog(@"%s",__func__);
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
                                                    message:@"Transaction restored" delegate:nil
                                          cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [alert show];
    [alert release];
#endif
    _purchasing = NO;
    if (_delegate && [_delegate respondsToSelector:@selector(angelDidRestoreTransactions:)]) {
        [_delegate angelDidRestoreTransactions:queue.transactions];
    }
    
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads{
#ifdef IAP_DEBUG
    NSLog(@"%s",__func__);
#endif
}

- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error{
#ifdef IAP_DEBUG
    NSLog(@"%s",__func__);
#endif
    _purchasing = NO;
    if (_delegate && [_delegate respondsToSelector:@selector(angelPaymentQueue:restoreCompletedTransactionsFailedWithError:)]) {
        [_delegate angelPaymentQueue:queue restoreCompletedTransactionsFailedWithError:error];
    }
}

- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions{
#ifdef IAP_DEBUG
    NSLog(@"%s",__func__);
#endif
}

@end
